package com.ryder.subject.domain.util;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * 描述: 抽取得缓存工具类
 *
 * @author Ryder
 * @version 1.0
 * @since 1.0 // 版本号，指明从哪个版本开始
 * 更新日期: 2025/03/07
 */
@Component
public class CacheUtil<K, V> {

    /**
     * 构建的本地缓存实例
     * <p>配置说明：</p>
     * - 最大缓存条目数：5000条
     * - 数据存活时间：写入后10秒自动过期
     * - 默认使用LRU算法淘汰最久未使用的数据
     */
    private Cache<String, String> localCache =
            CacheBuilder.newBuilder()
                    .maximumSize(5000)
                    .expireAfterWrite(10, TimeUnit.SECONDS)
                    .build();

    /**
     * 泛型缓存查询方法
     *
     * @param cacheKey      缓存键（唯一标识缓存数据）
     * @param clazz         目标数据类型的类对象（用于类型反序列化）
     * @param function      数据加载函数（定义缓存未命中时的数据获取逻辑）
     * @return             查询到的数据列表
     * @throws JSONException 如果JSON解析失败
     */
    public List<V> getResult(String cacheKey, Class<V> clazz,
                             Function<String, List<V>> function) {
        List<V> resultList = new LinkedList<>();
        String content = localCache.getIfPresent(cacheKey);
        if (StringUtils.isNotBlank(content)) {
            resultList = JSON.parseArray(content, clazz);
        } else {
            resultList = function.apply(content);
            if (!CollectionUtils.isEmpty(resultList)) {
                localCache.put(cacheKey, JSON.toJSONString(resultList));
            }
        }
        return resultList;
    }

    /**
     * 泛型Map类型缓存查询方法（待实现）
     *
     * @param cacheKey      缓存键
     * @param clazz         目标数据类型的类对象
     * @param function      数据加载函数
     * @return             查询到的数据映射
     */
    public Map<K, V> getMapResult(String cacheKey, Class<V> clazz,
                               Function<String, Map<K, V>> function) {
        return new HashMap<>();
    }

}